CVE-2012-1875简单分析
在IE漏洞中,UAF是广为存在的,所以这一次想调试学习一下这类型的漏洞,也熟悉了解一些IE的机制。如有错误或意见,还请斧正和提出,感激不尽。
调试环境
Windows7 sp1 x86
IE8.0.7601.17514
修改过后的简易POC:
<html>
<body>
<title></title>
<DIV id=testfaild>
<img id="test">
<div id="test"></div>
<input id="what" onMouseOver="crash();"></input>
</DIV>
<script language="JavaScript">
function crash() {
test.src = "";
}
function trigger() {
Math.tan(0);
var x = document.getElementsByTagName("input");
Math.tan(0);
x[0].fireEvent("onMouseOver");
Math.sin(0);
testfaild.innerHTML = testfaild.innerHTML;
Math.cos(0);
x[0].fireEvent("onMouseOver");
}
trigger();
</script>
</BODY>
</HTML>
打开PoC后,崩溃信息如下:
看来是某个Element释放后重用所导致的。IE在解析DOM树的过程中会使用CCollectionCache结构将所创建的元素缓存以加速查询,在第一次执行crash函数时,CCollectionCache::GetDisp 会调用CCollectionCache::BuildNamedArray、CMarkup::AddToCollections 来函数遍历HTML页面中所有具有id属性的标签在内存中的对象,创建一个具有"test"id属性的对象所组成的数组,通过 CImplPtrAry::Copy 将上述数组保存至新创建的CElementAryCacheItem 对象中。
打开Windbg附加进程,下如下断点:
运行后断在断点0处,在IDA加载符号表后找到mshtml.dll中CCollectionCache::CCollectionCache
在Windbg单步执行完该函数,查看CCollectionCache对象
第一次断在tan语句时,查看CCollectionCache对象(05b7dfd0即为上文中esi的值)
可以看到其保留的数组大小为0x0d,先来查看Index 0
接着需要重点关注Index 8中对应元素CElementAryCacheItem中的内容:
可以看到其ArraySize为4,
对应着我们在PoC中定义的对象。
接着我们在开始提到的,在第一次执行crash函数时,会创建一个具有"test"id属性的对象所组成的数组,数组会保存在Index e处。在执行之前,我们先来看看那里现在的情况。(在两个tan语句中间获取input对象时,CCollectionCache结构体中Item数组大小及首地址均变化,因重复打开后地址随机化,故此处0720dfd对应着之前CCollectionCache对象的地址)
(当执行 getElementsByTagName 语句且在 CImplPtrAry::Copy 断下时,可以自己试试找找准备拷贝的id为input的对象数组,此处略)
在执行tan与sin之间的crash函数时,代码在 BuildNamedArray 函数之后断在 CImplPtrAry::Copy 处,在Index e处新建了一个CElementAryCacheItem 待赋值。
可以发现此时ecx中保存着新 CElementAryCacheItem 对象地址,DWORD PTR[EAX+C] 中保存着被拷贝的id为“test”对象数组:
单步执行至 CImplPtrAry::Copy 函数结束后,新 CElementAryCacheItem 完成赋值。
sin与cos之间,语句 testfailed.innnerHTML=testfailed.innnerHTML 会使得当前页面中所有标签在内存中的对象被销毁,并依次重新创建相关类型的对象。所以当执行过该语句后,CollectionsCacheItem 数组Index E位置上的NewCacheItem中保存的已经是被释放了的对象的内存地址。
当PoC中第二次调用crash函数时,会使用GetDispID查询对应的元素是否需要重建。在IDA中可以得到GetDispID的堆栈调用:
CCollectionCache::GetDispID
CCollectionCache::EnsureAry
CCollectionCache::GetIntoAry
CCollectionCache::GetAtomFromName
http://zenhumany.blog.163.com/blog/static/1718066332013926101149471/中提到“在CCollectionCache::EnsureAry中会对查询的CatchItem是否有效进行验证,验证的方法是(见下图):
其当前的版本lCurrentVersion和它引用的原始的CacheItem的版本是否一致,如果不一致,需要根据原始版本重新构建给定的CacheItem。”
最终在本PoC中,程序会再次读取已释放的CCollectionCache Index e处的CElementAryCacheItem,造成异常。
参考目录
http://zenhumany.blog.163.com/blog/static/1718066332013926101149471/
https://bbs.pediy.com/thread-152240.htm
本文由看雪论坛 luobobo 原创
转载请注明来自看雪论坛
往期热门阅读:
扫描二维码关注我们,更多干货等你来拿!